package cn.edu.buaa.etei.native2ascii;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

public class PropertiesBuilder extends IncrementalProjectBuilder{
	private static final String PROPERTIES = ".properties";
	public static final String JAVA_BUILDER_NAME = "org.eclipse.jdt.core.javabuilder";
	public static String BUILDER_NAME = "cn.edu.buaa.etei.native2ascii.builder";

	@SuppressWarnings("unchecked")
	@Override
	protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
			throws CoreException {
		IResourceDelta delta = getDelta(getProject());
		if(kind == FULL_BUILD || delta == null){
			getProject().accept(new IResourceVisitor(){
				public boolean visit(IResource resource) throws CoreException {
					native2ascii(resource);
					return true;
				}
			});
		} else {
			delta.accept(new IResourceDeltaVisitor(){
				public boolean visit(IResourceDelta delta) throws CoreException {
					switch(delta.getKind()){
					case IResourceDelta.ADDED:
					case IResourceDelta.CHANGED:
						native2ascii(delta.getResource());break;
					case IResourceDelta.REMOVED:
						break;
					}
					return true;
				}
			});
		}
		return null;
	}

	private void native2ascii(IResource resource) throws CoreException {
		if(!resource.getName().endsWith(PROPERTIES)){
			return;
		}
		IJavaElement srcFolder = JavaCore.create(resource.getParent());
		if(srcFolder == null){
			return;
		}
		if(srcFolder.getElementType() == IJavaElement.PACKAGE_FRAGMENT){
			srcFolder = srcFolder.getParent();
		}
		if(srcFolder.getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT){
			return;
		}
		IJavaProject jproject = JavaCore.create(resource.getProject());
		IPath outputLocation = jproject.getOutputLocation();
		IFile file = (IFile) resource;
		StringBuffer buff = new StringBuffer();
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(file.getContents(), file.getCharset()));
			String line = null;
			while((line = in.readLine()) != null){
				buff.append(native2Ascii(line)).append('\n');
			}
			in.close();
		} catch (IOException e) {
			IWorkbench workbench = PlatformUI.getWorkbench();
			IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
			IStatus status = new Status(IStatus.ERROR, 
					Activator.getDefault().getBundle().getSymbolicName(), 
					"Exception thown while reading resource:" + file.getName(), 
					e);
			ErrorDialog.openError(window.getShell(), "Error read native2ascii setting", "Exception thrown while reading native2ascii builder setting", status );
			Activator.getDefault().getLog().log(status);
		}
		ByteArrayInputStream bin = new ByteArrayInputStream(buff.toString().getBytes());
		IPath path = file.getProjectRelativePath().removeFirstSegments(srcFolder.getResource().getProjectRelativePath().segmentCount());
		IPath destFilePath = outputLocation.append(path);
		IFolder folder = jproject.getProject().getFolder(destFilePath.removeFirstSegments(1).removeLastSegments(1));
		IFile destFile = folder.getFile(destFilePath.lastSegment());
		if(destFile.exists()){
			destFile.setContents(bin, false, false, null);
		} else {
			destFile.create(bin, false, null);
		}
	}

	private static String native2Ascii(String str) {
		StringBuffer sb = new StringBuffer(str.length());
		sb.setLength(0);
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			sb.append(native2Ascii(c));
		}
		return (new String(sb));
	}

	private static StringBuffer native2Ascii(char charater) {
		StringBuffer sb = new StringBuffer();
		if (charater > 255) {
			sb.append("\\u");
			int lowByte = (charater >>> 8);
			sb.append(int2HexString(lowByte));
			int highByte = (charater & 0xFF);
			sb.append(int2HexString(highByte));
		} else {
			sb.append(charater);
		}
		return sb;
	}

	private static String int2HexString(int code) {
		String hexString = Integer.toHexString(code);
		if (hexString.length() == 1)
			hexString = "0" + hexString;
		return hexString;
	}

}
